package com.brayan.webapp.repository.general.i18n;

import java.util.LinkedList;
import java.util.List;

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.log4j.Logger;

import com.brayan.webapp.model.general.i18n.Text;
import com.brayan.webapp.model.general.i18n.Text_;
import com.brayan.webapp.model.general.i18n.Translation;
import com.brayan.webapp.model.general.i18n.Translation_;

@Stateless
public class TextRepository {

	@Inject
	transient private Logger LOGGER; 

	@PersistenceContext(unitName = "ccms")
	EntityManager em;
	
	@Inject
	TranslationRepository translationRepo;

	public List<Text> getTextUnitsByTokenOrText(String searchFilter) {
		List<Text> ongoingReservations = new LinkedList<Text>();
		CriteriaBuilder critBuilder = em.getCriteriaBuilder();
		CriteriaQuery<Text> criteriaQuery = critBuilder.createQuery(Text.class);
		Root<Text> rootText = criteriaQuery.from(Text.class);

		Predicate finalPredicate = null, orPredicate, tokenPredicate, textPredicate, translatedTextPredicate;
		// finalPredicate =
		// critBuilder.greaterThanOrEqualTo(text.get(Text_.endDate), new
		// Date());

		// cb.equal(reservation.get("email"), email));
		criteriaQuery.orderBy(critBuilder.asc(rootText.get(Text_.token)));

		if (searchFilter == null || searchFilter.isEmpty()) {

		} else {
			Join<Text, Translation> translation = rootText.join(Text_.translation);

			Expression<String> tokenExpression = translation.get(Translation_.translation);
			Expression<String> textExpression = translation.get(Translation_.translation);
			Expression<String> translatedTextExpression = translation.get(Translation_.translation);

			String tokenPattern = searchFilter + "%";
			String textPattern = "%" + searchFilter + "%";
			String translatedTextPattern = "%" + searchFilter + "%";

			tokenPredicate = critBuilder.like(tokenExpression, tokenPattern);
			textPredicate = critBuilder.like(textExpression, textPattern);
			translatedTextPredicate = critBuilder.like(translatedTextExpression, translatedTextPattern);

			orPredicate = critBuilder.or(tokenPredicate, textPredicate, translatedTextPredicate);
			finalPredicate = critBuilder.and(orPredicate);
		}
		criteriaQuery.select(rootText).where(finalPredicate);
		ongoingReservations = em.createQuery(criteriaQuery).getResultList();
		return ongoingReservations;
	}

	/**
	 * Return a limited number of records.
	 * 
	 * @param nRecords
	 * @return
	 */
	public List<Text> getTextsUnits(Integer nRecords) {
		List<Text> textUnits = new LinkedList<Text>();
		CriteriaBuilder critBuilder = em.getCriteriaBuilder();
		CriteriaQuery<Text> criteriaQuery = critBuilder.createQuery(Text.class);
		Root<Text> text = criteriaQuery.from(Text.class);
		criteriaQuery.select(text);
		// cb.equal(reservation.get("email"), email));
		criteriaQuery.orderBy(critBuilder.asc(text.get(Text_.token)));
		if (nRecords == null || nRecords == 0)
			textUnits = em.createQuery(criteriaQuery).getResultList();
		else
			textUnits = em.createQuery(criteriaQuery).setMaxResults(nRecords).getResultList();
		return textUnits;
	}

	public Text getText(Long id) {
		return em.find(Text.class, id);
	}

	public void saveTextToken(Text text) {
		em.merge(text);
	}
	
	/**
	 * Get the translation of a text.
	 * 
	 * @param id
	 * @return
	 */
	public List<Translation> getTranslationsByTextId(Long id) {
		return translationRepo.getTranslationsByTextId(id);
	}

	public Text deleteText(long textId) {
		translationRepo.deleteText(textId);
		return null;
	}

	public Text getTextUnitByToken(String token) {
		CriteriaBuilder critBuilder = em.getCriteriaBuilder();
		CriteriaQuery<Text> criteriaQuery = critBuilder.createQuery(Text.class);

		Root<Text> rootText = criteriaQuery.from(Text.class);
		criteriaQuery.select(rootText);
		criteriaQuery.where(
				critBuilder.equal(rootText.get(Text_.token), token)
				);

		TypedQuery<Text> typedQuery = em.createQuery(criteriaQuery);

		Text text = null;
		try {
			text = typedQuery.getSingleResult();
		} catch (NoResultException nrEx) {
			LOGGER.info("No default text found for token " + token + ".");
		}

		return text;		
	}
}
